2. Hadoop 分布式

搭建 Hadoop 分布式

准备机器

克隆两个虚拟机,修改主机名和网络,分别如下

1
2
3
hadoop10  192.168.1.10
hadoop11 192.168.1.11
hadoop12 192.168.1.12

因为是克隆的虚拟机,所以 java 环境,rexyan 用户在伪分布式都有了,所以这些步骤就不重复了。hadoop 因为之前进行了配置,所以会重装。三个虚拟机,要求每个内存至少 4G,且都选择了时区和进行时间的同步,

因为台机器会互相拷贝和传输文件,所以需要开启免密登录,这里以 192.168.1.10 为主要的机器,他会往 192.168.1.11 和 192.168.1.12 拷贝文件,所以配置 192.168.1.10 在 192.168.1.11 和 192.168.1.12 的免密登录。在 192.168.1.10 上执行

1
2
3
4
5
6
7
8
ssh-keygen -t rsa  # 生成 192.168.1.10 的密钥信息
ssh-copy-id hadoop10 # 将密钥信息拷贝到 自己,实现免密登录
ssh-copy-id hadoop11 # 将密钥信息拷贝到 hadoop11,实现免密登录
ssh-copy-id hadoop12 # 将密钥信息拷贝到 hadoop12,实现免密登录

ssh hadoop10 # 测试是否能免密登上 自己
ssh hadoop11 # 测试是否能免密登上 hadoop11
ssh hadoop12 # 测试是否能免密登上 hadoop12

编写集群文件分发脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
#校验参数是否合法
if(($#==0))
then
echo 请输入要分发的文件!
exit;
fi
#获取分发文件的绝对路径
dirpath=$(cd `dirname $1`; pwd -P)
filename=`basename $1`

echo 要分发的文件的路径是:$dirpath/$filename

#循环执行rsync分发文件到集群的每条机器
for((i=10;i<=12;i++))
do
echo ---------------------hadoop$i---------------------
rsync -rvlt $dirpath/$filename rexyan@hadoop$i:$dirpath
done

例如,需要在 hadoop10 tmp 目录下创建 test 文件,并将文件分发到 hadoop11,hadoop12 中的 tmp 目录下

这样就能将 10 下面的 /tmp/test 文件拷贝到 11 和 12 下面

规划集群

重新规划集群角色如下:

1
2
3
4
5
hadoop10					hadoop11					hadoop12

DataNode DataNode DataNode
NodeManager NodeManager NodeManager
NameNode ResourceManager SecondaryNamenode

安装 Hadoop

解压上传好的 hadoop 到 /opt/module/

1
tar -zxvf /opt/soft/hadoop-2.7.2.tar.gz -C /opt/module/

配置 core-site.xml 将 hdfs 配置成为分布式,因为规划的是在 10上启动 namenode,所以配置文件中 value为 10的地址

1
2
3
4
5
6
7
8
9
10
11
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://hadoop10:9000</value>
</property>

<property>
<name>hadoop.tmp.dir</name>
<value>/opt/module/hadoop-2.7.2/data/tmp</value>
</property>
</configuration>

在 hdfs-site.xml 中配置 2NN(SecondaryNamenode),按照规划 2NN 是配置到 hadoop12 机器上的,所以 value 要写 hadoop12 的地址。

1
2
3
4
5
6
<configuration>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>hadoop12:50090</value>
</property>
</configuration>

配置 yarn-site.xml,按照规划 ResourceManager 运行在 hadoop11,所以 value 指定 ResourceManager 运行的机器为 hadoop11

1
2
3
4
5
6
7
8
9
10
11
12
13
<configuration>
<!-- 获取数据的方式 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>

<!-- 指定YARN的ResourceManager的地址 -->
<property>
<name>yarn.resourcemanager.hostname</name>
<value>hadoop11</value>
</property>
</configuration>

将 mapred-site.xml.template 文件复制另一份为 mapred-site.xml,并在其中设置 mapreduce 的运行方式为 yarn

1
2
3
4
5
6
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>

利用集群分发脚本,将配置好的 hadoop 文件分发到其他机器

1
bash xsync /opt/module/hadoop-2.7.2/

分别配置三台机器的环境变量,将 hadoop 加入到坏境变量中,如果没有配置 java 的环境变量,也需要进行配置

1
2
3
JAVA_HOME=/opt/module/jdk1.8.0_121
HADOOP_HOME=/opt/module/hadoop-2.7.2
PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

使用 SSH 执行在远端执行命令及问题

在 10 机器上,执行 ssh hadoop11 jps,提示 找不到 jps 命令,但是 hadoop11 的确已经配置了 java 的环境变量了的。

1
[rexyan@hadoop10 ~]$ ssh hadoop11 jps

为什么会发生这种现象呢,因为 ssh 一台机器后马上执行某命令,这样的没有交互的登录方式叫做 Non-Login shell,这种 Non-Login shell 执行登录脚本的顺序是

1
2
3
1. ~/.bashrc
2. /etc/bashrc
3. /etc/profile.d/目录下的脚本

因为我们的环境变量是添加到 /etc/profile 下面的,没有在 Non-Login shell 的加载顺序中,所以提示找不到 jps 命令。解决方法就是在 /etc/bashrc 中 source /etc/profile。这样就算是以 Non-Login shell 的方式执行命令,那么也能找到 /etc/profile 下设置的环境变量,也就能找到 jps 命令。

所以我们需要在所有机器的 /etc/bashrc 中添加 source /etc/profile

编写集群执行同一命令脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
#在集群的所有机器上批量执行同一条命令
if(($#==0))
then
echo 请输入您要操作的命令!
exit
fi

echo 要执行的命令是$*

#循环执行此命令
for((i=10;i<=12;i++))
do
echo ---------------------hadoop$i-----------------
ssh hadoop$i $*
done

例如,在所有机器上执行 ifconfig,只需执行 bash xcall ifconfig 即可

1
bash xcall ifconfig

启动 HDFS

在启动 hdfs 之前,我们需要对 namenode 进行格式化,因为 namenode 是在 hadoop10 机器上的,所以需要在 hadoop10 机器上执行

1
hadoop namenode -format

在 hadoop10 上启动 namenode

1
hadoop-daemon.sh start  namenode

在 hadoop10,hadoop11,hadoop12 上启动 datanode

1
bash xcall hadoop-daemon.sh start datanode

在 hadoop12 上启动 SecondaryNamenode

1
hadoop-daemon.sh start secondarynamenode

查看各机器启动状态

1
bash xcall jps

访问 web 页面看是成功,因为 namenode 是在 10 上的,所以访问 http://192.168.1.10:50070/ 即可

启动 YARN

ResourceManager 是规划在 hadoop11 机器上的,所以在 hadoop11 启动 ResourceManager

1
yarn-daemon.sh  start resourcemanager

在 hadoop10,hadoop11,hadoop12 上启动 nodemanager

1
bash xcall yarn-daemon.sh  start nodemanager

访问 web 页面看是否存在文件,resourcemanager 是在 hadoop11 上启动的,所以访问 http://192.168.1.11:8088/cluster ,可以看到三个 nodemanager 也启动了。

测试集群

创建一个文件夹,上传一个文件到创建好的 hdfs 文件夹中

1
2
hadoop fs -mkdir /wcinput3
hadoop fs -put hello2 /wcinput3

测试 yarn,并查询运行结果

1
2
hadoop jar hadoop-mapreduce-examples-2.7.2.jar wordcount /wcinput3 /wcoutput3
hadoop fs -cat /wcoutput3/part-r-00000

群启脚本

在 /opt/module/hadoop-2.7.2/sbin 目录下有很多启动和停止的脚本,可以不用一个一个去执行和停止 hdfs 进程和 yarn 进程,群启脚本可以批量启动和停止。

群起脚本的原理是获取集群中所有的节点的主机名,默认读取当前机器 HADOOP_HOME/etc/hadoop/slaves,获取集群中所有的节点的主机名。循环执行 ssh 主机名 hadoop-daemon.sh start xxx 所以需要保证当前机器(需要执行群启的机器)到其他节点,已经配置了ssh免密登录,保证集群中所有机器当前用户的家目录/.bashrc中,已经配置 source /etc/profile。

注意⚠️:start-all.sh 时,其实分别调用了start-dfs.sh 和 start-yarn.sh,start-dfs.sh 可以在集群的任意一台机器使用!可以启动 HDFS 中的所有进程。start-yarn.sh 在集群的非RM所在的机器使用,不会启动resourcemanager, stop-yarn.sh 也是一样的,不会停止 resourcemanager 。所以,建议是配置 RM 所在机器到其他机器的 SSH 免密登录,都在 RM 所在的机器执行群起和群停脚本 xsync 和 xcall 只放在 RM 所在的机器即可(上面我们不是这样的,上面我们的规划是 11 是 RM 所在的机器,但是 10 配置了到所有机器的免密登录,xsync 和 xcall 脚本)

在 10 上配置 slaves 文件

1
2
3
hadoop10
hadoop11
hadoop12

停止所有服务,然后查看状态

1
2
3
stop-all.sh 
cd ~
bash xcall jps

群启 hdfs

群启 yarn

单独在 11 上启动 resourcemanager

1
yarn-daemon.sh start resourcemanager

日志服务

为了方便查看日志,需要为 10 机器配置日志收集服务,修改 mapred-site.xml, 添加如下配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- 机器 10 配置jobhistory服务 -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>hadoop10:10020</value>
</property>

<!-- 将收集的日志提供 web 访问 -->
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>hadoop10:19888</value>
</property>

<!--第三方框架使用yarn计算的日志聚集功能,例如 spark 等框架 -->
<property>
<name>yarn.log.server.url</name>
<value>http://hadoop10:19888/jobhistory/logs</value>
</property>
1
2
3
4
5
6
7
8
9
10
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>

<!-- 日志保留时间设置7天 -->
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>604800</value>
</property>

在 10 机器上将脚本进行分发到其他机器,然后停止并重启集群

1
2
3
bash xsync /opt/module/hadoop-2.7.2/etc/hadoop/  # 注意这里只同步了配置文件的目录
stop-all.sh
start-all.sh

在 12 上重启 resourcemanager

1
yarn-daemon.sh stop resourcemanager

在 10 上启动日志服务

1
mr-jobhistory-daemon.sh start historyserver

再次执行任务

1
hadoop jar hadoop-mapreduce-examples-2.7.2.jar wordcount /wcinput3 /wcoutput4

通过 yarn 的 web 页面查看日志